package l1j.server.server.model.skill;
import l1j.opqlo.Server.L1World.L1World;
import l1j.server.server.ActionCodes;
import l1j.server.server.model.L1Character;
import l1j.server.server.model.L1Object;
import l1j.server.server.model.Instance.L1ItemInstance;
import l1j.server.server.model.Instance.L1MonsterInstance;
import l1j.server.server.model.Instance.L1NpcInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.model.map.L1Map;
import l1j.server.server.model.map.L1WorldMap;
import l1j.server.server.serverpackets.S_DoActionGFX;
import l1j.server.server.serverpackets.S_EffectLocation;
import l1j.server.server.serverpackets.S_UseAttackSkill;
import static l1j.server.server.model.skill.L1SkillId.ABSOLUTE_BARRIER;
import static l1j.server.server.model.skill.L1SkillId.EARTH_BIND;
import static l1j.server.server.model.skill.L1SkillId.FREEZING_BLIZZARD;
import static l1j.server.server.model.skill.L1SkillId.FREEZING_BREATH;
import static l1j.server.server.model.skill.L1SkillId.ICE_LANCE;
import static l1j.server.server.model.skill.L1SkillId.IMMUNE_TO_HARM;
import static l1j.server.server.model.skill.L1SkillId.NPC_FREEZING_BREATH;

public class L1SpecialSkillAction {

	public static void SpecialSkillAction(final L1Character _user,
			final int AttackGfxid, final int HitGfxid, final int Range) {

		final L1PcInstance pc = (L1PcInstance) _user;

		int x2 = pc.getX();
		int y2 = pc.getY();
		switch(pc.getHeading()) {
		case 1: x2 += Range; y2 -= Range; break;
		case 2: x2 += Range; break;
		case 3: x2 += Range; y2 += Range; break;
		case 4: y2 += Range; break;
		case 5: x2 -= Range; y2 += Range; break;
		case 6: x2 -= Range; break;
		case 7: x2 -= Range; y2 -= Range; break;
		case 0: y2 -= Range; break;
		}
		final int NewX = x2;
		final int NewY = y2;
		final S_UseAttackSkill packet2 = new S_UseAttackSkill(pc, 0,
				AttackGfxid, NewX, NewY, ActionCodes.ACTION_Attack, false);
		pc.sendPackets(packet2);
		pc.broadcastPacketAll(packet2);

		int x = pc.getX();
		int y = pc.getY();
		for (int i = 0; i < Range; i++) {
			final int a = pc.targetDirection(x, y);
			switch(a) {
			case 1: x++; y--; break;
			case 2: x++; break;
			case 3: x++; y++; break;
			case 4: y++; break;
			case 5: x--; y++; break;
			case 6: x--; break;
			case 7: x--; y--; break;
			case 0: y--; break;
			}
			final L1Map map = L1WorldMap.getInstance().getMap(pc.getMapId());
			if (!map.isArrowPassable(x, y, pc.getHeading())) {
				break;
			}
			for (final L1Object object : L1World.getInstance().getVisibleObjects(_user, Range)) {
				if (object == null) {
					continue;
				}

				if (!(object instanceof L1Character)) {
					continue;
				}

				final L1Character target = (L1Character) object;

				if (target instanceof L1PcInstance && target.getZoneType() == 1) {
					continue;
				}

				if (target.isDead()) {
					continue;
				}

				if (target.isInvisble()) {
					continue;
				}

				if (target instanceof L1PcInstance)  {
					final L1PcInstance targetPc = (L1PcInstance) target;
					if (targetPc.isGmInvis()) {
						continue;
					}
				}

				if (target instanceof L1MonsterInstance) {
					final L1MonsterInstance targetNpc = (L1MonsterInstance) target;
					final int hiddenStatus = targetNpc.getHiddenStatus();
					if (hiddenStatus == L1NpcInstance.HIDDEN_STATUS_SINK
							|| hiddenStatus == L1NpcInstance.HIDDEN_STATUS_FLY) {
						continue;
					}
				}

				if (target.getX() == x && target.getY() == y && !target.isDead()
						&& !target.hasSkillEffect(ICE_LANCE)
						&& !target.hasSkillEffect(EARTH_BIND)
						&& !target.hasSkillEffect(FREEZING_BLIZZARD)
						&& !target.hasSkillEffect(FREEZING_BREATH)
						&& !target.hasSkillEffect(ABSOLUTE_BARRIER)
						&& !target.hasSkillEffect(NPC_FREEZING_BREATH)
						&& (target instanceof L1PcInstance
								|| target instanceof L1MonsterInstance)) {

					int Damage = 0;

					L1ItemInstance weapon = null;

					weapon = pc.getWeapon();

					if (weapon != null) {
						final int WeaponDmg = weapon.getItem().getDmgSmall()
								+ weapon.getItem().getDmgLarge();
						final int WeaponAddDmg = weapon.getItem().getDmgModifier()
						+ weapon.getEnchantLevel();
						final int PcDmg = pc.getDmgup();
						final int pcCha = pc.getCha();
						Damage = (WeaponDmg + WeaponAddDmg + PcDmg + pcCha) * 5;
					} // 這裡是抄反擊屏障的傷害式

					if (target.hasSkillEffect(IMMUNE_TO_HARM)) {
						Damage *= 2;
					} //只看聖結界不看抗魔

					final S_EffectLocation packet = new S_EffectLocation(x, y, HitGfxid);
					final S_DoActionGFX packet3 = new S_DoActionGFX(target.getId(),ActionCodes.ACTION_Damage);

					if (target instanceof L1PcInstance) {
						final L1PcInstance targetPc = (L1PcInstance) target;
						targetPc.sendPackets(packet);
						targetPc.sendPackets(packet3);
						targetPc.receiveDamage(pc, Damage, false);
					} else if (target instanceof L1MonsterInstance) {
						final L1MonsterInstance targetNpc = (L1MonsterInstance) target;
						targetNpc.receiveDamage(pc, Damage);
					}
					target.broadcastPacketAll(packet);
					target.broadcastPacketAll(packet3);
				}
			}
		}
	}

}